﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


/*!
*@file ExprEngineIntf.h
*@brief 表达式引擎接口单元
*@author hexm
*@date 2011.3.16
*@version 0.1
*@remarks Copyright (c) 1998-2011 Glodon Corporation
*/
#ifndef EXPR_ENGINEINTF_H
#define EXPR_ENGINEINTF_H

#ifdef _MSC_VER
#ifdef EXPRENGINE_EXPORTS
#define EXPR_ENGINE_API __declspec(dllexport)
#else
#define EXPR_ENGINE_API __declspec(dllimport)
#endif
#else
#define EXPR_ENGINE_API
#endif

#include <list>
#include <set>
#include "OwnerPtr.h"
#include "UnitHelper.h"


/*表达式计算结果数据类型 */
typedef enum
{
    edtUnknown     = 0,
    edtInteger     = 1,  //整数
    edtBoolean   = 2,  //布尔类型
    edtFloat     = 3,  //浮点类型
    edtString     = 4   //字符串类型
}ExprDataType;


/*表达式节点类型*/
/*
etOperate-运算符，如+、-、*、\
etConst-常量，如果100,'宽度'等
etID-标识符，如Name
etFunction-函数
*/
typedef enum
{
    etUnaryOperate        = 0,  //一元操作符
    etBinaryOperate        = 1,  //二元操作符
    etConst                = 2,  //常量
    etID                = 3,  //唯一识别的变量
    etExpr                = 4,  //嵌套的表达式节点
    etFunction            = 5   //自定义函数
} ExprType;

#define MaxStringValueLength 16


/*!
*@class ExprNodeData
*@brief 表达式节点数据对象
*@author hexm
*@date 2011.3.16
*/
class EXPR_ENGINE_API ExprNodeData
{
public:
    /*!
    *@brief 获得数据值类型
    *@return
    *@remarks 如果表达式非法，edtUnknown
    */
    virtual ExprDataType GetType() const = 0;
    /*!
    *@brief 获得单位
    *@return
    *@remarks 如果表达式非法，edtUnknown
    */
    virtual UnitMap GetUnitType() = 0;
    /*!
    *@brief 设置单位
    *@return
    *@remarks 如果表达式非法，edtUnknown
    */
    virtual void SetUnitType(const UnitMap& unitType) = 0;
    /*!
    *@brief 设置整型值
    *@return
    *@remarks
    */
    virtual void SetAsInteger(long AValue) = 0;
    /*!
    *@brief 得到整型值
    *@return
    *@remarks
    */
    virtual long GetAsInteger() const = 0;
    /*!
    *@brief 设置布尔值
    *@remarks
    */
    virtual void SetAsBoolean(bool AValue) = 0;
    /*!
    *@brief 得到布尔值
    *@return
    *@remarks
    */
    virtual bool GetAsBoolean() const = 0;
    /*!
    *@brief 设置浮点型值
    *@return
    *@remarks
    */
    virtual void SetAsFloat(double AValue) = 0;
    /*!
    *@brief 得到浮点型值
    *@return
    *@remarks
    */
    virtual double GetAsFloat() const = 0;
    /*!
    *@brief 设置字符串值
    *@return
    *@remarks
    */
    virtual void SetAsString(const wchar_t* AValue) = 0;
    /*!
    *@brief 得到字符串值
    *@return
    *@remarks
    */
    virtual const wchar_t* GetAsString() const = 0;
};

/*!
*@class ExprNode
*@brief 表达式语法树节点类
*@author hexm
*@date 2011.3.16
*/
class EXPR_ENGINE_API ExprNode
{
public:
    virtual ~ExprNode(){}
    /*!
    *@brief 得到节点类型
    *@return
    *@remarks
    */
    virtual ExprType GetNodeType() const = 0;
    /*!
    *@brief 得到节点数据
    *@return
    *@remarks
    */
    virtual ExprNodeData* GetData() = 0;
    /*!
    *@brief 得到数据值类型
    *@return
    *@remarks
    */
    virtual ExprDataType GetDataType() const = 0;
    /*!
    *@brief 得到数据值单位
    *@return
    *@remarks
    */
    virtual UnitMap GetUnitType() = 0;
    /*!
    *@brief 设置节点标记，用于记录额外信息
    *@return
    *@remarks
    */
    virtual void SetTag(void* ATag) = 0;
    /*!
    *@brief 得到节点标记
    *@return
    *@remarks
    */
    virtual void* GetTag() const = 0;
};

/*!

*@class ExprNodeVisitor
*@brief 访问表达式的节点
*@author mlw
*@date 2013.12.5
*/
class EXPR_ENGINE_API ExprNodeVisitor
{
public:
    virtual void Visit(const ExprNode* pNode) = 0;
};

/*!

*@class FunctionParams
*@brief 函数参数列表
*@author hexm
*@date 2011.3.16
*/
class EXPR_ENGINE_API FunctionParams
{
public:
    /*!
    *@brief 添加参数，表达式引擎内部使用
    *@return
    *@remarks
    */
    virtual ExprNode* AppendParams(gcmp::OwnerPtr<ExprNode> AParam)=0;
    /*!
    *@brief 参数个数
    *@return
    *@remarks
    */
    virtual short Count() const = 0;
    /*!
    *@brief 根据索引值获得参数
    *@return 对于非法索引返回NULL
    *@remarks
    */
    virtual ExprNodeData* GetParam(short AIndex) = 0;
    virtual ~FunctionParams(){};
};

/*!

*@class IExprNodeDataProvider
*@brief 使用者需要继承此类提供表达式求值过程中的必要信息
*@author hexm
*@date 2011.3.16
*/
class EXPR_ENGINE_API IExprNodeDataProvider
{
public:
    virtual ~IExprNodeDataProvider(){}
    /*!
    *@brief 设置节点值类型
    *@param[in] Name，节点的Code
    *@return
    *@remarks
    */
    virtual ExprDataType GetResultDataType(const wchar_t* Name)=0;//设置节点值类型

    /*!
    *@brief 获得节点数值单位
    *@param[in] Name，节点的Code
    *@return
    *@remarks
    */
    virtual ExprUnitType GetUnitType(const wchar_t* Name)=0;//获得节点数值单位
    /*!
    *@brief 设置节点的值
    *@param[in] Name，节点的Code
    *@param[in] Data，用户通过Data设置节点的值
    *@param[in] ATag，节点标记
    *@return
    *@remarks
    */
    virtual void SetExprData(const wchar_t* Name, ExprNodeData* Data ,void* ATag=NULL)=0; //设置节点数据

    virtual void ListExprData(std::list<std::wstring>& names) {};
};

/*!
*@class IExprCustomFunction
*@brief 自定义函数的基类
*@author hexm
*@date 2011.3.16
*/
class EXPR_ENGINE_API IExprCustomFunction
{
public:
    virtual ~IExprCustomFunction(){}
    /*!
    *@brief 函数名称
    *@return
    *@remarks
    */
    virtual const wchar_t* GetFunctionName() = 0; //函数名称
    /*!
    *@brief 函数返回值类型
    *@return
    *@remarks
    */
    virtual ExprDataType GetResultDataType() = 0; //函数返回值类型
    /*!
    *@brief 执行函数
    *@param[in] Params，函数参数
    *@param[in] ResultData，节点值，通过ResultData设置函数值
    *@param[in] ATag 节点标记
    *@return
    *@remarks
    */
    virtual bool DoExectute(FunctionParams* Params, ExprNodeData* ResultData, void* ATag=NULL) = 0;//函数求值
};

class EXPR_ENGINE_API IExprEngine;

/*!
*@enum EnErrorType
*@brief 错误类型
*@author lius-j
*@date 2017.2.7
*/
enum EXPR_ENGINE_API EnErrorType
{
    //未定义的错误类型
    ET_UNDEFINE,
    //某个变量或数字后是一个左括号
    ET_LPAREN_AFTER_PARAM,
    //右括号前面没有对应的左括号
    ET_REDUNDANT_RPAREN,
    //最后一个字符是二目操作符
    ET_LAST_BINARY,
    //括号对里内容为空
    ET_NULL_EXPR_IN_PARENS,
    //除数或者模数为0
    ET_DIVISOR_IS_ZERO,
    //单位计算无效
    ET_UNIT_INVALID,
};

/*!
*@class IExprParser
*@brief 表达式解析器
*@author hexm
*@date 2011.3.16
*/
class EXPR_ENGINE_API IExprParser
{
public:
    /*!
    *@brief 设置表达式
    *@return 返回把函数名转为内置大小写格式后的表达式字符串
    *@remarks 设置表达式并不会进行计算
    */
    virtual wchar_t* SetExpression(const wchar_t* AValue) = 0;
    /*!
    *@brief 计算表达式
    *@remarks 调用此方法后才能够取得表达式的值
    */
    virtual void Evaluate() =0 ;
    /*!
    *@brief 获取表达式的返回值类型
    *@return 如果表达式非法，将返回edtUnknown
    *@remarks
    */
    virtual ExprDataType ResultType() const = 0;    
    /*!
    *@brief 获取表达式的返回单位
    *@return 如果表达式单位无效，将返回FamilyParameterType::Invalid
    *@remarks
    */
    virtual UnitMap ResultUnitType() = 0;
    /*!
    *@brief 获取表达式的返回值
    *@return 如果表达式非法，将返回NULL
    *@remarks
    */
    virtual ExprNodeData* Result() = 0;
    /*!
    *@brief 获取表达式是否为空
    *@return
    *@remarks
    */
    virtual bool GetIsNull() const = 0;
    /*!
    *@brief 获取表达式是否合法
    *@return
    *@remarks
    */
    virtual bool GetIsValid() const = 0;

    /*!
    *@brief 获取表达式是错误位置
    *@return 错误的位置
    *@remarks
    */
    virtual int GetErrorPos() const = 0;

    /*!
    *@brief 获取表达式错误类型
    *@return 错误类型
    *@remarks
    */
    virtual EnErrorType GetErrorType() const = 0;

    /*!
    *@brief 访问所有的节点
    *@param[in] pVisitor，访问器
    *@return
    *@remarks
    */
    virtual void Accept(ExprNodeVisitor* pVisitor) const = 0;

    /*!
    *@brief 是否循环引用了某个标识符
    *@param[in] 标识符名字
    *@return
    *@remarks
    */
    virtual bool IsCircularReferenced(const wchar_t* tokenName) const = 0;

    /*!
    *@brief 获取表达式引用的所有参数名
    *@return 表达式引用的所有参数名列表
    *@remarks 列表中只包括该表达式直接引用的参数名
    */
    virtual void GetAllReferencedParamNames(std::set<const wchar_t*> &refParamNames) const = 0;

    virtual const IExprEngine* GetEngine() const = 0;
    virtual ~IExprParser(){}

    virtual const ExprNode* GetRootNode() const = 0;

    virtual std::vector<const wchar_t*> GetExprNodeNames() const = 0;
};

/*!

*@class IExprEngine
*@brief 表达式引擎
*@author hexm
*@date 2011.3.16
*/
class EXPR_ENGINE_API IExprEngine
{
public:
    virtual gcmp::OwnerPtr<IExprParser> CreateParser() = 0;
public:
    /*!
    *@brief 设置节点数据提供者对象
    */
    virtual void SetNodeDataProvider(gcmp::OwnerPtr<IExprNodeDataProvider> pDataProvider) = 0;

    /*!
    *@brief 获取节点数据提供者对象
    *@return 数据供应器指针
    */
    virtual IExprNodeDataProvider* GetNodeDataProvider() = 0;

    /*!
    *@brief 注册自定义函数
    *@param[in] AFunction，用户自定义函数，由用户创建并管理
    *@return
    *@remarks
    */
    virtual void RegisterFunction(IExprCustomFunction* AFunction) = 0;
    /*!
    *@brief 反自定义函数
    *@param[in] AFunction，用户自定义函数，由用户创建并管理
    *@return
    *@remarks
    */
    virtual void UnRegisterFunction(IExprCustomFunction* AFunction) = 0;
    /*!
    *@brief 查找函数
    *@param[in] AName，函数名称
    *@return 如果没有找到返回NULL
    *@remarks
    */
    virtual IExprCustomFunction* FindFunction(const wchar_t* AName) = 0 ;

    /*!
    *@brief 查找函数并调整函数名的大小写
    *@param[in/out] AName，函数名称，大小写不敏感
    *@return 如果没有找到返回NULL，且不会调整函数名
    *@remarks 如果找到了，会把函数名调整为内置的大小写格式
    */
    virtual IExprCustomFunction* FindFunctionAndAdjustName(wchar_t* AName) = 0;

    /*!
    *@brief 注册表达式
    *@param[in] const wchar_t* AExprParserName 表达式变量名称
    *@param[in] IExprParser* pNewExprParser 表达式对象指针
    *@return true 注册成功 false 注册失败
    */
    virtual bool RegisterExprParser(const wchar_t* pExprParserName, gcmp::OwnerPtr<IExprParser> pNewExprParser) = 0;

    /*!
    *@brief 反注册表达式
    *@param[in] const wchar_t* AExprParserName 表达式变量名称
    *@return 被反注册的表达式对象指针
    */
    virtual bool UnRegisterExprParser(const wchar_t* pExprParserName) = 0;

    /*!
    *@brief 根据唯一的名称搜索已经注册的表达式对象
    *@param[in] const wchar_t* AExprParserName 表达式变量名称
    *@return 表达式对象指针
    */
    virtual IExprParser* FindParser(const wchar_t* pExprParserName) = 0;

    virtual void Regenerate(const std::list<std::wstring>& changedNames) = 0;

    virtual ~IExprEngine(){}
};

//创建IExprEngine
EXPR_ENGINE_API gcmp::OwnerPtr<IExprEngine> CreateEngine();
//创建IExprParser
EXPR_ENGINE_API gcmp::OwnerPtr<IExprParser> CreateParser();
#endif

